package com.web.base.wechat.provider;

import com.blue.core.dict.State;
import com.blue.core.util.RandomUtil;
import com.blue.core.util.RandomUtil.RandomType;
import com.blue.wechat.auth.SignUtil;
import com.blue.wechat.cache.Wechat;
import com.blue.wechat.invoke.WechatContainer;
import com.blue.wechat.invoke.WechatInvoker;
import com.blue.wechat.invoke.model.JsApiTicket;
import com.blue.wechat.invoke.model.menu.Menu;
import com.blue.wechat.invoke.model.menu.MenuItem;
import com.blue.wechat.invoke.model.menu.MenuType;
import com.blue.wechat.invoke.model.oauth.OAuthAccessToken;
import com.blue.wechat.invoke.model.user.UserInfo;
import com.web.base.wechat.cache.WechatCache;
import com.web.base.wechat.exception.WechatException;
import com.web.base.wechat.exception.WechatInvokerException;
import com.web.base.wechat.facade.WechatInvokerFacade;
import com.web.base.wechat.message.JsApiTicketResponse;
import com.web.base.wechat.message.UserInfoResponse;
import com.web.base.wechat.model.WechatMenu;
import com.web.base.wechat.service.WechatMenuService;
import com.web.base.wechat.util.UserInfoConvertor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
public class WechatInvokerProvider implements WechatInvokerFacade
{
	private static Logger logger = LoggerFactory.getLogger(WechatInvokerProvider.class);
	
	@Resource
	private WechatMenuService wechatMenuService;
	@Resource
	private WechatCache wechatCache;
	@Autowired(required = false)
	private WechatContainer wechatContainer;
	
	public WechatInvokerProvider()
	{
	}

	@Override
	public UserInfoResponse getOAuthUserInfo(String code, String state)
	{
		Wechat wechat = wechatCache.getByCode(state);
		if (wechat == null)
			throw new WechatException("微信号不存在[code=" + state + "]");
			
		OAuthAccessToken token = wechatContainer.invoke(state, WechatInvoker.OAUTH_ACCESS_TOKEN, null, code);
		if (token == null)
			return null;
		
		UserInfo userInfo = wechatContainer.invoke(state, WechatInvoker.OAUTH_USER_INFO, null, token.getAccessToken(), token.getOpenid());
		UserInfoResponse response = UserInfoConvertor.toResponse(userInfo);
		return response;
	}

	@Override
	public JsApiTicketResponse geJsApiTicket(String code, String url)
	{
		Wechat wechat = wechatCache.getByCode(code);
		if (wechat == null)
			throw new WechatException("微信号不存在[code=" + code + "]");
		
		JsApiTicket ticket = wechatContainer.invoke(code, WechatInvoker.JS_API_TICKET, null);
		if (ticket == null)
			throw new WechatInvokerException("微信号[code=" + code + "] 获取 js-api-ticket 失败");
		
		JsApiTicketResponse response = new JsApiTicketResponse();
		response.setAppId(wechat.getAppId());
		response.setUrl(url);
		response.setNonceStr(RandomUtil.rand(RandomType.UPPER_LOWER_CASE_NUMBER, 16));
		response.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000));
		
		String signature = SignUtil.jsApiTicket(response.getNonceStr(), ticket.getTicket(), response.getTimestamp(), url);
		logger.info("生成 js-api-ticket 签名：{}", signature);
		
		response.setSignature(signature);
		
		return response;
	}

	@Override
	public void syncMenu(String code)
	{
		Wechat wechat = wechatCache.getByCode(code);
		if (wechat == null)
			throw new WechatException("微信号不存在[code=" + code + "]");
		
		WechatMenu wechatMenu = new WechatMenu();
		wechatMenu.setWechatId(wechat.getId());
		wechatMenu.setState(State.NORMAL);
		Map<String, List<WechatMenu>> menuMap = wechatMenuService.listMenu(wechatMenu);
		if (menuMap.isEmpty())
			return;
		
		Menu menu = new Menu();
		List<WechatMenu> rootList = menuMap.get("0");
		if (rootList != null && !rootList.isEmpty())
		{
			for (WechatMenu rootMenu : rootList)
			{
				MenuItem menuItem = new MenuItem();
				menuItem.setName(rootMenu.getName());
				menuItem.setType(MenuType.geType(rootMenu.getType()));
				menuItem.setKey(rootMenu.getKey());
				menuItem.setUrl(rootMenu.getUrl());
				menu.add(menuItem);
				
				List<WechatMenu> subList = menuMap.get(String.valueOf(rootMenu.getId()));
				if (subList != null && !subList.isEmpty())
				{
					List<MenuItem> subButton = new ArrayList<>();
					for (WechatMenu subMenu : subList)
					{
						MenuItem subItem = new MenuItem();
						subItem.setName(subMenu.getName());
						subItem.setType(MenuType.geType(subMenu.getType()));
						subItem.setKey(subMenu.getKey());
						subItem.setUrl(subMenu.getUrl());
						subButton.add(subItem);
					}
					menuItem.setSubButton(subButton);
				}
			}
			
		}
		wechatContainer.invoke(code, WechatInvoker.DELETE_MENU, null);
		wechatContainer.invoke(code, WechatInvoker.CREATE_MENU, menu);
	}
	
	
}
